﻿import kliment.math.Calc;
import kliment.geom.color.*;
/**
 * ...
 * @author	Kliment
 * @version	1.2.0
 */
class kliment.geom.color.RGBColor extends ColorAbstract {
	private var WHITE:Number = 255;
	
	public var rawR:Number = 0;
	public var rawB:Number = 0;
	public var rawG:Number = 0;
	
	function RGBColor(host:Color) {
		super(host);
	}
	
	public function get r():Number { return rawR * WHITE }
	public function get g():Number { return rawG * WHITE }
	public function get b():Number { return rawB * WHITE }
	
	public function setValue(r:Number, g:Number, b:Number, update:Boolean):Void {
		setRawValue(r / WHITE, g / WHITE, b / WHITE, update);
	}
	
	public function setRawValue(r:Number, g:Number, b:Number, update:Boolean ):Void {
		if (update == undefined) update = true;
		if (rawR == r && rawG == g && rawB == b)
			return;
		rawR = Calc.inInterval(MIN_RAW, MAX_RAW, r);
		rawG = Calc.inInterval(MIN_RAW, MAX_RAW, g);
		rawB = Calc.inInterval(MIN_RAW, MAX_RAW, b);
		
		if (color && update)
			color.valueChanged(Color.RGB);
	}
	
	public function toString():String {
		return "[RGBColor r=" + r + " g=" + g + " b=" + b + "]";
	}
	
	public function clone():RGBColor {
		var result:RGBColor = new RGBColor();
		result.setRawValue(rawR, rawG, rawB, false);
		return result;
	}
	
	public function toHSV(hsv:HSVColor):HSVColor { return converToHSV(this, hsv) }
	static public function converToHSV(rgb:RGBColor, hsv:HSVColor):HSVColor {
		if (!hsv) hsv = new HSVColor();
		var r:Number = rgb.rawR; 
		var g:Number = rgb.rawG;
		var b:Number = rgb.rawB;
		
		var min:Number = Math.min(r, Math.min(g, b)); 
		var max:Number = Math.max(r, Math.max(g, b));
		var delta:Number = max - min;
		var h:Number; 
		var s:Number;
		switch (max) {
			case min: h = 0; break;
			case r: 
					h = 60 * (g - b) / delta; 
					if (g < b) { 
						h += 360; 
					} 
			break;
			case g: h = (60 * (b - r) / delta) + 120; break;
			case b: h = (60 * (r - g) / delta) + 240; break;
		}
		s = (max === 0)?0:(1 - (min / max));
		hsv.setRawValue(h/360, s, max, false);
		
		/*var r:Number = rgb.rawR;
		var g:Number = rgb.rawG;
		var b:Number = rgb.rawB;
		var h:Number;
		
		var min:Number = Math.min(r, Math.min(g, b)); 
		var max:Number = Math.max(r, Math.max(g, b));
		var delta:Number = max - min;
		var s:Number = (r > b ? r : (g > b ? g : b)) == 0 ? 0 : (delta / max);
		var temp:Number = ((r > b ? r : (g > b ? g : b)) == 0 ? 0 : (delta / max)) == 0 ? (1e-005) : delta;
		
		switch(max)	{
		case r:
			h = (g - b) / temp;
		break;
		case g:
			h = 2 + (b - r) / temp;
		break;
		case b:
			h = 4 + (r - g) / temp;
		break;
		}
		
		hsv.setRawValue(h / 6, s, max, false);*/
		return hsv;
	}
	
	public function toXYZ(xyz:XYZColor):XYZColor { return converToXYZ(this, xyz) }
	static public function converToXYZ(rgb:RGBColor, xyz:XYZColor):XYZColor {
		if (!xyz) xyz = new XYZColor();
		
		var r:Number = rgb.rawR;
		var g:Number = rgb.rawG;
		var b:Number = rgb.rawB;
		r = r > .04045 ? (Math.pow((r + .055) / 1.055, 2.4)) : (r / 12.92);
		g = g > .04045 ? (Math.pow((g + .055) / 1.055, 2.4)) : (g / 12.92);
		b = b > .04045 ? (Math.pow((b + .055) / 1.055, 2.4)) : (b / 12.92);
		var x:Number = (.4124 * r + 0.3576 * g + .1805 * b) * 100 / 95.047;
		var y:Number = .2126 * r + 0.7152 * g + .0722 * b;
		var z:Number = (.0193 * r + 0.1192 * g + .9505 * b) * 100 / 108.883;
		xyz.setRawValue(x, y, z, false);
		return xyz;
	}
	
	public function toCMYK(cmyk:CMYKColor):CMYKColor { return converToCMYK(this, cmyk) }
	static public function converToCMYK(rgb:RGBColor, cmyk:CMYKColor):CMYKColor {
		if (!cmyk) cmyk = new CMYKColor();
		
		var r:Number = 1 - rgb.rawR;
		var g:Number = 1 - rgb.rawG;
		var b:Number = 1 - rgb.rawB;
		
		var k:Number = Math.min(r, g, b);
		
		var c:Number = (r - k) / (1 - k);
		var m:Number = (g - k) / (1 - k);
		var y:Number = (b - k) / (1 - k);
		
		cmyk.setRawValue(c, m, y, k, false);
		return cmyk;
	}
}